#ifndef ELEMTAB_H_
#define ELEMTAB_H_
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "esmd_types.h"
// #include "htab.h"
#include "htab_cpp.hpp"
typedef esmd::htab<cchar_key, typeint> elemtab_t;
// typedef struct element {
//   elemstr name;
//   typeint id;
// } element_t;

// #define ELEM_HASH(x) (htab_hash_string((x)->name))
// #define ELEM_EQ(x, y) (!strcmp((x)->name, (y)->name))

// HTAB_DEFINE_ESMD(elemtab, element_t, ELEM_HASH, ELEM_EQ)
#define ELEMTAB_NONE -1
#define ELEMTAB_WILD -2

static inline typeint elemtab_map(elemtab_t *tab, const elemstr s) {
  return tab->setdefault(s, tab->size());
}
// static inline typeint elemtab_map(elemtab_t *tab, elemstr s) {
//   element_t *cast_ent = (element_t *)s;
//   element_t **slot = elemtab_find_slot(tab, cast_ent);
//   assert(slot);
//   if (htab_slot_is_empty(slot)) {
//     element_t *esmd_icalloc1(ent, "elem tab/record");
//     strcpy(ent->name, s);
//     ent->id = (typeint)tab->cnt;
//     //*slot = ent;
//     elemtab_insert(tab, slot, ent);
//   }
//   return (*slot)->id;
// }

static inline typeint elemtab_set_wild(elemtab_t *tab, const elemstr s) {
  (*tab)[s] = ELEMTAB_WILD;
  return ELEMTAB_WILD;
}

static inline void elemtab_unset_wild(elemtab_t *tab, const elemstr s) {
  tab->remove(s);
}

static inline typeint elemtab_get(elemtab_t *tab, const elemstr s) {
  return tab->get(s, ELEMTAB_NONE);
}

// typedef struct topent {
//   typeint type[4];
//   typeint id;
//   int cnt;
// } topent_t;

// #define TOP_HASH(x) (htab_iterative_hash((x)->type, sizeof(typeint) * (size_t)(x)->cnt, 0))
// #define TOP_EQ(x, y) ((x)->cnt == (y)->cnt && !memcmp((x)->type, (y)->type, (size_t)(x)->cnt * sizeof(typeint)))

// HTAB_DEFINE_ESMD(toptab, topent_t, TOP_HASH, TOP_EQ)

// static inline typeint toptab_map(toptab_t *tab, topent_t *s) {
//   topent_t *cast_ent = (topent_t *)s;
//   topent_t **slot = toptab_find_slot(tab, cast_ent);
//   assert(slot);
//   if (htab_slot_is_empty(slot)) {
//     topent_t *esmd_icalloc1(ent, "elem tab/record");
//     ent->type[0] = s->type[0];
//     ent->type[1] = s->type[1];
//     ent->type[2] = s->type[2];
//     ent->type[3] = s->type[3];
//     ent->cnt = s->cnt;
//     ent->id = (typeint)tab->cnt;
//     //*slot = ent;
//     toptab_insert(tab, slot, ent);
//   }
//   return (*slot)->id;
// }

// static inline typeint toptab_get(toptab_t *tab, topent_t *s) {
//   topent_t *cast_ent = (topent_t *)s;
//   topent_t **slot = toptab_find_slot(tab, cast_ent);
//   assert(slot);
//   if (htab_slot_is_empty(slot))
//     return ELEMTAB_NONE;
//   return (*slot)->id;
// }
#endif
